/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { formatTime, Module } from '@ohos/hvigor';

import { ModuleType } from '../enum/module-type-enum.js';
import { AbstractModulePlugin } from '../plugin/common/abstract-module-plugin.js';
import { initializeArkTsTasks } from '../tasks/manager/arkts-task-initializer.js';
import {
  AssembleHapCA,
  AssembleHarCA,
  AssembleHqfCA,
  AssembleHspCA,
  BuildHotReloadResourceCA,
  BuildPreviewerResCA,
  CleanCA,
  CompileNativeHookCA,
  DeviceTestHookCA,
  GeneratedBuildProfileCA,
  GenOnDeviceTestHapCA,
  HotReloadBuildCA,
  LibraryBuildPreviewerResCA,
  PreviewBuildCA,
  PreviewHookCompileResourceCA,
  TestCA,
  UnitTestBuildCA,
} from '../tasks/manager/global-task-creation-manager.js';
import { initNativeTasks } from '../tasks/manager/native-task-initializer.js';
import { initResourceTasks } from '../tasks/manager/resource-task-initializer.js';
import { ModuleTaskService } from '../tasks/service/module-task-service.js';
import { TargetTaskService } from '../tasks/service/target-task-service.js';
import {
  ArkLinterCA,
  BeforeGenerateDeviceCoverageCA,
  BuildProfileTaskCA,
  BuildUnitTestHookCA,
  CopyPreviewProfileCA,
  GenerateDeviceCoverageCA,
  GenerateLoaderJsonCA,
  GenerateMetadataCA,
  GeneratePkgContextInfoCA,
  GeneratePkgModuleJsonCA,
  GenerateUnitTestResultCA,
  GenerateUnitTestTemplateCA,
  HarBuildProfileTaskCA,
  MakePackInfoCA,
  MergeProfileCA,
  OhosTestCopyMockConfigJsonCA,
  PackageHapCA,
  FastPackageCA,
  PackageHarCA,
  PackageHqfCA,
  PackageHspCA,
  PackageSharedHarCA,
  PackageSharedTgzCA,
  PreBuildCA,
  PreCheckSyscapCA,
  PrepareSharedHarResCA,
  PreviewCompileResourceCA,
  PreviewUpdateAssetsCA,
  ProcessIntegratedHspCA,
  ProcessObfuscationFilesCA,
  ProcessOhPackageJsonCA,
  ProcessPackageJsonCA,
  ProcessProfileCA,
  ProcessRouterMapCA,
  ProcessStartupConfigCA,
  ReplacePreviewerPageCA,
  ReplaceUnitTestIndexFileCA,
  ReplaceSourceMapInCoverageModeCA,
  SignHapCA,
  PackageSignHarCA,
  SignHqfCA,
  SignHspCA,
  SignModuleRemoteHspCA,
  SignProjectRemoteHspCA,
  SyscapTransformCA,
  UnitTestCopyMockConfigJsonCA,
  UnitTestProcessProfileCA,
  GenerateOhosTestTemplateCA,
  CreateHarModuleInfoCA,
  ProcessHarArtifactsCA,
  CollectDebugSymbolCA,
  FastPackageHspCA,
  CreateModuleInfoCA,
} from '../tasks/manager/task-creation-manager.js';
import { TaskCreatorManager } from '../tasks/task-creator.js';
import { OhosLogger } from './log/ohos-logger.js';
import { isFastBuildApp } from './task-util.js';
import { initializeArkTsV2Tasks } from '../arkts-evolution/tasks/manager/arkts-v2-task-initializer.js';

const log = OhosLogger.getLogger('TaskInitialization');

export class TaskInitializer {
  /**
   *
   * @param plugin
   */
  static initializeHap(plugin: AbstractModulePlugin) {
    const start: [number, number] = process.hrtime();
    const moduleTaskService: ModuleTaskService = plugin.getTaskService()!;
    const module: Module = plugin.getModuleModel()!.getModule();
    const creatorManager: TaskCreatorManager = new TaskCreatorManager(module.getTaskContainer());

    // 初始化hook任务
    creatorManager.registry(new AssembleHapCA(moduleTaskService, plugin));
    this.commonHap(plugin, creatorManager);

    // 初始化target任务
    this.initializeTargetTasks(plugin, creatorManager);
    log.debug(`Module ${module.getName()} task initialization takes ${formatTime(process.hrtime(start))}`);
    return creatorManager;
  }

  static initializeHsp(plugin: AbstractModulePlugin) {
    const start: [number, number] = process.hrtime();
    const moduleTaskService: ModuleTaskService = plugin.getTaskService()!;
    const module: Module = plugin.getModuleModel()!.getModule();
    const creatorManager: TaskCreatorManager = new TaskCreatorManager(module.getTaskContainer());

    // 初始化hook任务
    creatorManager.registry(new AssembleHspCA(moduleTaskService, plugin));
    creatorManager.registry(new GenOnDeviceTestHapCA(moduleTaskService, plugin));
    this.commonHap(plugin, creatorManager);

    // 初始化target任务
    this.initializeTargetTasks(plugin, creatorManager);
    log.debug(`Module ${module.getName()} task initialization takes ${formatTime(process.hrtime(start))}`);
    return creatorManager;
  }

  /**
   *
   * @param plugin
   */
  static initializeHar(plugin: AbstractModulePlugin) {
    const start: [number, number] = process.hrtime();
    const moduleTaskService: ModuleTaskService = plugin.getTaskService()!;
    const module: Module = plugin.getModuleModel()!.getModule();
    const creatorManager: TaskCreatorManager = new TaskCreatorManager(module.getTaskContainer());

    // 初始化hook任务
    creatorManager.registry(new AssembleHarCA(moduleTaskService, plugin));
    creatorManager.registry(new LibraryBuildPreviewerResCA(moduleTaskService, plugin));
    creatorManager.registry(new GeneratedBuildProfileCA(moduleTaskService, plugin, false, true));
    this.initializeCommonHookTasks(plugin, creatorManager);

    // 初始化hook任务
    creatorManager.registry(new GenOnDeviceTestHapCA(moduleTaskService, plugin));

    // 初始化target任务
    this.initializeTargetTasks(plugin, creatorManager);
    log.debug(`Module ${module.getName()} task initialization takes ${formatTime(process.hrtime(start))}`);
    return creatorManager;
  }

  private static commonHap(plugin: AbstractModulePlugin, creatorManager: TaskCreatorManager) {
    const moduleTaskService: ModuleTaskService = plugin.getTaskService()!;
    creatorManager.registry(new BuildPreviewerResCA(moduleTaskService, plugin));
    creatorManager.registry(new HotReloadBuildCA(moduleTaskService, plugin));
    creatorManager.registry(new GeneratedBuildProfileCA(moduleTaskService, plugin, false, false));
    creatorManager.registry(new AssembleHqfCA(moduleTaskService, plugin));
    this.initializeCommonHookTasks(plugin, creatorManager);
  }

  private static initializeCommonHookTasks(plugin: AbstractModulePlugin, creatorManager: TaskCreatorManager) {
    const moduleTaskService: ModuleTaskService = plugin.getTaskService()!;
    creatorManager.registry(new CompileNativeHookCA(moduleTaskService, plugin));
    creatorManager.registry(new PreviewBuildCA(moduleTaskService, plugin));
    creatorManager.registry(new UnitTestBuildCA(moduleTaskService, plugin));
    creatorManager.registry(new TestCA(moduleTaskService, plugin));
    creatorManager.registry(new BuildHotReloadResourceCA(moduleTaskService, plugin));
    creatorManager.registry(new CleanCA(moduleTaskService, plugin));
    creatorManager.registry(new DeviceTestHookCA(moduleTaskService, plugin));
  }

  private static initializeTargetTasks(plugin: AbstractModulePlugin, creatorManager: TaskCreatorManager) {
    plugin.getNeedExecTargetServiceList().forEach((target) => this.targetInitialize(target, creatorManager));
  }

  /**
   * target任务初始化入口
   *
   * @param service
   * @param creatorManager
   * @private
   */
  public static targetInitialize(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    this.hapTasksInitialize(service, creatorManager);
    this.hspTasksInitialize(service, creatorManager);
    this.harTasksInitialize(service, creatorManager);
    this.initializeCommonTargetTasks(service, creatorManager);
  }

  private static hapTasksInitialize(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    const moduleType = service.getModuleService().getModuleModel().getModuleType();
    if (moduleType !== ModuleType.Entry && moduleType !== ModuleType.Feature) {
      return;
    }
    this.tasksInitialize(service, creatorManager);

    if (isFastBuildApp(service.getModuleService())) {
      creatorManager.registry(new FastPackageCA(service));
    } else {
      creatorManager.registry(new PackageHapCA(service));
      creatorManager.registry(new SignHapCA(service));
    }
  }

  private static hspTasksInitialize(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    const moduleType = service.getModuleService().getModuleModel().getModuleType();
    if (moduleType !== ModuleType.Shared) {
      return;
    }
    this.tasksInitialize(service, creatorManager);

    if (isFastBuildApp(service.getModuleService())) {
      creatorManager.registry(new FastPackageHspCA(service));
    } else {
      creatorManager.registry(new PackageSharedHarCA(service));
      creatorManager.registry(new PrepareSharedHarResCA(service));
      creatorManager.registry(new PackageSharedTgzCA(service));
    }

    creatorManager.registry(new PackageHspCA(service));
    creatorManager.registry(new SignHspCA(service));
    creatorManager.registry(new SignHapCA(service));
    creatorManager.registry(new PackageHapCA(service));
  }

  private static harTasksInitialize(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    const moduleType = service.getModuleService().getModuleModel().getModuleType();
    if (moduleType !== ModuleType.Har) {
      return;
    }
    creatorManager.registry(new ProcessHarArtifactsCA(service));
    creatorManager.registry(new PackageHarCA(service));
    creatorManager.registry(new PackageSignHarCA(service));
    creatorManager.registry(new ArkLinterCA(service));
    creatorManager.registry(new ProcessObfuscationFilesCA(service));
    creatorManager.registry(new ProcessOhPackageJsonCA(service));
    creatorManager.registry(new ProcessPackageJsonCA(service));
    creatorManager.registry(new HarBuildProfileTaskCA(service));
    creatorManager.registry(new CreateHarModuleInfoCA(service));
    creatorManager.registry(new SyscapTransformCA(service));
    creatorManager.registry(new MakePackInfoCA(service));
    creatorManager.registry(new GenerateMetadataCA(service));
    creatorManager.registry(new PackageHapCA(service));
    creatorManager.registry(new SignHapCA(service));
  }

  /**
   * hap/hsp所需任务, har不需要
   *
   * @param service
   * @param creatorManager
   * @private
   */
  private static tasksInitialize(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    creatorManager.registry(new SyscapTransformCA(service));
    creatorManager.registry(new CreateModuleInfoCA(service));
    creatorManager.registry(new MakePackInfoCA(service));
    creatorManager.registry(new GenerateMetadataCA(service));
    creatorManager.registry(new PackageHqfCA(service));
    creatorManager.registry(new SignHqfCA(service));
  }

  /**
   * hap/hsp/har所需任务
   *
   * @param service
   * @param creatorManager
   * @private
   */
  private static initializeCommonTargetTasks(service: TargetTaskService, creatorManager: TaskCreatorManager) {
    initializeArkTsTasks(service, creatorManager);

    // 初始化ArkTS1.2任务
    initializeArkTsV2Tasks(service, creatorManager);

    initResourceTasks(creatorManager, service);
    initNativeTasks(creatorManager, service);
    creatorManager.registry(new PreBuildCA(service));
    creatorManager.registry(new GenerateLoaderJsonCA(service));
    creatorManager.registry(new ProcessProfileCA(service));
    creatorManager.registry(new MergeProfileCA(service));
    creatorManager.registry(new PreviewHookCompileResourceCA(service));
    creatorManager.registry(new BuildProfileTaskCA(service));
    creatorManager.registry(new PreviewUpdateAssetsCA(service));
    creatorManager.registry(new BuildUnitTestHookCA(service));
    creatorManager.registry(new ReplaceSourceMapInCoverageModeCA(service));
    creatorManager.registry(new ReplaceUnitTestIndexFileCA(service));
    creatorManager.registry(new UnitTestProcessProfileCA(service));
    creatorManager.registry(new ReplacePreviewerPageCA(service));
    creatorManager.registry(new CopyPreviewProfileCA(service));
    creatorManager.registry(new PreviewCompileResourceCA(service));
    creatorManager.registry(new OhosTestCopyMockConfigJsonCA(service));
    creatorManager.registry(new UnitTestCopyMockConfigJsonCA(service));
    creatorManager.registry(new SignProjectRemoteHspCA(service));
    creatorManager.registry(new SignModuleRemoteHspCA(service));
    creatorManager.registry(new PreCheckSyscapCA(service));
    creatorManager.registry(new GenerateUnitTestTemplateCA(service));
    creatorManager.registry(new GenerateOhosTestTemplateCA(service));
    creatorManager.registry(new GenerateUnitTestResultCA(service));
    creatorManager.registry(new ProcessRouterMapCA(service));
    creatorManager.registry(new ProcessStartupConfigCA(service));
    creatorManager.registry(new GenerateDeviceCoverageCA(service));
    creatorManager.registry(new BeforeGenerateDeviceCoverageCA(service));
    creatorManager.registry(new GeneratePkgContextInfoCA(service));
    creatorManager.registry(new ProcessIntegratedHspCA(service));
    creatorManager.registry(new GeneratePkgModuleJsonCA(service));
    creatorManager.registry(new CollectDebugSymbolCA(service));
  }
}
